Skip to content

Commit

Permalink
feat(GifPlayer): adds component to pause and play gifs for a11y (#676)
Browse files Browse the repository at this point in the history
* v1.17.2

* v1.17.3

* feat: add gif player to pause and play gifs

* feat: test gif player in image gallery

* fix: gif player in dialog and hidden styles

* fix: gif player inside image gallery

* fix: gif player example images

* fix: selector names

* Update packages/gatsby-theme-carbon/src/components/GifPlayer/GifPlayer.js

Co-Authored-By: DAK <40970507+dakahn@users.noreply.github.com>

* Update packages/gatsby-theme-carbon/src/components/GifPlayer/GifPlayer.js

Co-Authored-By: DAK <40970507+dakahn@users.noreply.github.com>

* fix: focus for ff

* fix: pause play label

Co-authored-by: DAK <40970507+dakahn@users.noreply.github.com>
  • Loading branch information
jnm2377 and dakahn authored Jan 27, 2020
1 parent 726016c commit 27d356c
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 5 deletions.
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
aria-pressed={paused ? 'true' : 'false'}
type="button"
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

1 comment on commit 27d356c

@vercel
Copy link

@vercel vercel bot commented on 27d356c Jan 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.