Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(GifPlayer): adds component to pause and play gifs for a11y #676

Merged
merged 19 commits into from
Jan 27, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/example/src/data/nav-items.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
path: /components/DoDontRow
- title: FeatureCard
path: /components/FeatureCard
- title: GifPlayer
path: /components/GifPlayer
- title: Grid
path: /components/Grid
- title: ImageCard
Expand Down
83 changes: 83 additions & 0 deletions packages/example/src/pages/components/GifPlayer.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: GifPlayer
description: Usage instructions for the Accordion component
---

<PageDescription>

The `<GifPlayer>` component is used to pause and play images that are gif's. It works by replacing the gif with a static image on pause.

</PageDescription>

## Example

<Row>
<Column colLg='4'>

<Title>Light</Title>

<GifPlayer>

![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.gif)
![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.png)

</GifPlayer>
</Column>
</Row>


<Row>
<Column colLg='8'>

<Title>Dark</Title>

<GifPlayer color='dark'>

![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.gif)
![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.png)

</GifPlayer>
</Column>
</Row>

## Code

Place two images inside of the GifPlayer component. The first image will be used as the gif, the second image will be used as the static image on pause. Only provide two images inside the component, do not place any other children inside the component.

<Title>Light</Title>

```jsx path=components/GifPlayer/GifPlayer.js src= https://github.com/carbon-design-system/gatsby-theme-carbon/tree/master/packages/gatsby-theme-carbon/src/components/GifPlayer

<Column colLg='4'>
<GifPlayer>

![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.gif) // must be gif
![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.png) // must be static image

</GifPlayer>
</Column>

```

<Title>Dark</Title>

```jsx path=components/GifPlayer/GifPlayer.js src= https://github.com/carbon-design-system/gatsby-theme-carbon/tree/master/packages/gatsby-theme-carbon/src/components/GifPlayer

<Column colLg='8'>
<GifPlayer color='dark'>

![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.gif) // must be gif
![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.png) //must be static image

</GifPlayer>
</Column>

```

### Props

| property | propType | required | default | description |
| --------- | -------- | -------- | ------- | --------------------- |
| children | node | yes | | Pass in the images that will be rendered. Only pass in the images, no other children |
| color | string | | `light` | Specify if the icon color should be light or dark |
| className | string | | | Specify an optional className to be applied to the container node |
12 changes: 11 additions & 1 deletion packages/example/src/pages/components/ImageGallery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,22 @@ Click on an image to open the gallery.
</ImageGalleryImage>
<ImageGalleryImage alt="IBM Cloud Platform Prototype" title="IBM Cloud Platform" col={8}>

<GifPlayer color='dark'>

![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.gif)
![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.png)

</GifPlayer>

</ImageGalleryImage>
<ImageGalleryImage alt="IBM Cloud Pictograms" title="IBM Cloud Pictograms" col={4}>

<GifPlayer>

![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.gif)
![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.png)

</GifPlayer>

</ImageGalleryImage>
<ImageGalleryImage alt="IBM Cloud Server" title="IBM Cloud Server" col={4}>
Expand All @@ -67,7 +77,7 @@ Click on an image to open the gallery.
<track default src="/videos/vtt/hero-video.vtt" srcLang="en" />
</Video>

</ImageGalleryImage>
</ImageGalleryImage>
<ImageGalleryImage alt="IBM Cloud Think" title="IBM Cloud Think" col={4}>

![IBM Cloud Think](/images/IBM_Cloud_Think_Keynote.jpg)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/gatsby-theme-carbon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { AnchorLinks, AnchorLink } from './src/components/AnchorLinks';
export { default as PageDescription } from './src/components/PageDescription';
export { default as Video } from './src/components/Video/Video';
export { default as DoDontExample } from './src/components/DoDontExample';
export { default as GifPlayer } from './src/components/GifPlayer';
export { Row, Column, Grid } from './src/components/Grid';
export { default as Caption } from './src/components/Caption';
export { default as ResourceCard } from './src/components/ResourceCard';
Expand Down
106 changes: 106 additions & 0 deletions packages/gatsby-theme-carbon/src/components/GifPlayer/GifPlayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import {
PlayOutline24,
PlayOutlineFilled24,
PauseOutline24,
PauseOutlineFilled24,
} from '@carbon/icons-react';
import styles from './GifPlayer.module.scss';

const Pause = ({ hovering }) =>
hovering ? <PauseOutlineFilled24 /> : <PauseOutline24 />;

const Play = ({ hovering }) =>
hovering ? <PlayOutlineFilled24 /> : <PlayOutline24 />;

const ToggleIcon = ({ paused, hovering }) =>
paused ? <Play hovering={hovering} /> : <Pause hovering={hovering} />;

const GifPlayer = ({ children, color, className, isInDialog }) => {
const [paused, setPaused] = useState(false);
const [hovering, setHovering] = useState(false);

const onClick = () => {
setPaused(!paused);
};

const controlsClassNames = classnames({
[styles.controls]: true,
[styles.dark]: color === 'dark',
});

const containerClassNames = classnames({
[styles.container]: true,
[className]: className,
[styles.gifInDialog]: isInDialog,
});

const staticImageClassNames = classnames({
[styles.imgHidden]: true,
[styles.imgDisplayed]: paused,
});

const gifClassNames = classnames({
[styles.gifDisplayed]: true,
[styles.gifHidden]: paused,
});

const childrenArray = React.Children.toArray(children);

const labelText = paused
? 'Toggleable animation paused'
: 'Toggleable animation playing';

return (
<div className={containerClassNames}>
<div className={gifClassNames} aria-hidden={paused ? 'true' : false}>
{childrenArray[0]}
</div>
<div
className={staticImageClassNames}
aria-hidden={paused ? false : 'true'}
>
{childrenArray[1]}
</div>
<button
jnm2377 marked this conversation as resolved.
Show resolved Hide resolved
aria-pressed={paused ? 'true' : 'false'}
type="button"
jnm2377 marked this conversation as resolved.
Show resolved Hide resolved
aria-label={labelText}
className={controlsClassNames}
onMouseEnter={() => setHovering(true)}
onMouseLeave={() => setHovering(false)}
onClick={onClick}
>
<ToggleIcon hovering={hovering} paused={paused} />
</button>
</div>
);
};

GifPlayer.propTypes = {
/**
* Specify if icon color should be "dark" or "light"
*/
color: PropTypes.string,
/**
* Specify optional className
*/
className: PropTypes.string,
/**
* Only pass in the 2 images to be rendered, first must be gif, second must be static image
*/
children: PropTypes.arrayOf(PropTypes.element).isRequired,
/**
* Specify if the gifPlayer is inside the expanded ImageGallery (see ImageGallery.js)
*/
isInDialog: PropTypes.bool,
};

GifPlayer.defaultProps = {
color: 'light',
isInDialog: false,
};

export default GifPlayer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.container {
position: relative;
}

.controls {
position: absolute;
bottom: 1rem;
left: 1rem;
height: 1.5rem;
width: 1.5rem;
background: transparent;
outline: none;
border: none;
padding: 0;
}

.controls svg {
fill: white;
}

.dark svg {
fill: black;
}

.controls:focus svg {
outline: 2px solid $focus;
outline-offset: -2px;
}

//toggle static image
.img-hidden {
display: none;
}

.img-displayed {
display: block;
}

//toggle gif
.gif-displayed {
display: block;
}

.gif-hidden {
display: none;
}

//styles for gif player in image gallery
.gif-in-dialog {
top: 50%;
transform: translateY(-50%);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import GifPlayer from './GifPlayer';

export default GifPlayer;
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,17 @@ function ImageGallery({ children }) {
)}
</Column>
<Column colLg={6}>
{React.cloneElement(childrenAsArray[activeImageIndex], {
isInDialog: true,
})}
{childrenAsArray[activeImageIndex].props.children.props
.mdxType === 'GifPlayer'
? React.cloneElement(
childrenAsArray[activeImageIndex].props.children,
{
isInDialog: true,
}
)
: React.cloneElement(childrenAsArray[activeImageIndex], {
isInDialog: true,
})}
</Column>
<Column colLg={3} className={navButtonsContainer}>
{activeImageIndex + 1 < childrenAsArray.length && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
width: 100%;
}

.image-in-dialog img {
.image-in-dialog img,
.image-in-dialog button {
margin: $spacing-05 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { AnchorLink, AnchorLinks } from '../AnchorLinks';
import { Tab, Tabs } from '../Tabs';
import Link from '../Link';
import { Accordion, AccordionItem } from '../Accordion';
import GifPlayer from '../GifPlayer';
import ArtDirection from '../ArtDirection';
import MediumPosts from '../MediumPosts';
import Title from '../Title';
Expand Down Expand Up @@ -56,6 +57,7 @@ const components = {
DoDontRow,
Row,
Column,
GifPlayer,
Grid,
Caption,
ResourceCard,
Expand Down