Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

feat(Embed|Video): add components #1108

Merged
merged 32 commits into from
Apr 10, 2019

Conversation

stuartlong
Copy link
Member

@stuartlong stuartlong commented Mar 26, 2019

API Proposal

The goal of this proposal is to provide components similar to Image that work with video sources.

  1. The Video component is a very basic wrapper around the
  2. The Embed component is a more complex one that displays either an embedded video (GIF) or an embedded iFrame

Video Component

Essentially just the normal

 <Video
      src="https://github.com/bower-media-samples/big-buck-bunny-480p-30s/master/video.mp4"
      poster="https://github.com/bower-media-samples/big-buck-bunny-480p-30s/master/poster.jpg"
      variables={{ width: '600px' }}
  />

Problems

  1. Video is played through default HTML5 video controls. These controls are accessible, but only via the tab key. Ideally, a user would tab to the video and then use the arrow keys to navigate through the video controls, but not sure how to get this to work within the stardust framework

  2. Muted attribute doesn't work. I can't get the muted attribtue to appear on the outputted html:

      <Video muted />

    and

    <Video muted="true" />

    both result in

Embed Component

This component displays either an Image or Video comppnent based on whether the GIF is currently playing. We do this swap out due to memory issues with the

If a video isn't provided, an iFrame can be provided to embed instead

The component also adds key handling for space / enter when focused on the gif to play/pause it.

 <Emned
      video="https://github.com/bower-media-samples/big-buck-bunny-480p-5s/master/video.mp4"
      poster="https://github.com/bower-media-samples/big-buck-bunny-480p-5s/master/poster.jpg"
      variables={{ width: '600px' }}
      active={true}
  />

Problems

  1. Displaying SVG as ::after content. I display the play/pause button as an ::after pseudoelement so it doesn't take up any slots or room in the DOM. However, I couldn't find a way to use the stored icons SVG and instead had to hard code the svg within the styles file itself.

TODO

  • Conformance test
  • Minimal doc site example
  • Stardust base theme
  • Teams Light theme
  • Teams Dark theme
  • Teams Contrast theme
  • Confirm RTL usage
  • W3 accessibility check
  • Stardust accessibility check
  • Update glossary props table
  • Update the CHANGELOG.md

Adds the Video and VideoGif components along with documentation, styling, and tests.
Video is a basic wrapper around the base video HTML tag, however VideoGif is slightly
more complex. It swaps out between a Video and Image component based on if the GIF is
playing or not and adds a hover icon the user can click to start/stop the GIF.
Copy link
Member

@layershifter layershifter left a comment

Choose a reason for hiding this comment

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

@stuartlong great work, however from components perspective I want to add some separation there.

Video

We can definitely add this component and then iterate on it to apply styling to controls and add more props.

VideoGif

Instead of it, I propose to add Embed component that will allow to handle not only videos, but even iframes. See for reference, https://react.semantic-ui.com/modules/embed/

  1. Rename to VideoGif to Embed
  2. Add video shorthand slot, add iframe shorthand slot and use Box component
render() {
  const { iframe, video } = this.props

  return (
    <>
      {Video.create(video)}
      {Box.create(iframe, { defaultProps: { as: 'iframe' } })}
     </>
   )
}
  1. As we are trying to match SUIR API, I suggest to rename poster prop to placeholder and use shorthand for Image:
render() {
  const { placeholder } = this.props

  return (
    <>
      {Image.create(placeholder)}
     </>
   )
}


/**
* An video is a graphicical and audio representation of something.
* @accessibility
Copy link
Member

Choose a reason for hiding this comment

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

I suggest to drop accessibility part for initial implementation at all and introduce it later with sync with our accessibility team. What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds good for Video. For Video Gif, I'd like to keep in the key actions so that space/enter on GIFs still play/pause them. But if there's some issue there too we can take that up after the accessibility sync.

…at/stuartlo/video

# Conflicts:
#	packages/react/src/themes/teams/components/Icon/svg/icons/pause.tsx
#	packages/react/src/themes/teams/components/Icon/svg/icons/play.tsx
@layershifter layershifter changed the title feat: implements video and video gif component feat(Embed|Video): add components Apr 9, 2019
@codecov
Copy link

codecov bot commented Apr 9, 2019

Codecov Report

Merging #1108 into master will increase coverage by 0.05%.
The diff coverage is 88.23%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1108      +/-   ##
==========================================
+ Coverage   82.47%   82.53%   +0.05%     
==========================================
  Files         743      750       +7     
  Lines        8761     8846      +85     
  Branches     1236     1178      -58     
==========================================
+ Hits         7226     7301      +75     
- Misses       1520     1530      +10     
  Partials       15       15
Impacted Files Coverage Δ
packages/react/src/themes/teams/index.ts 92% <ø> (ø) ⬆️
...ges/react/src/themes/base/components/Icon/index.ts 100% <ø> (ø) ⬆️
...rc/themes/teams/components/Embed/embedVariables.ts 100% <100%> (ø)
packages/react/src/index.ts 100% <100%> (ø) ⬆️
...kages/react/src/themes/teams/componentVariables.ts 100% <100%> (ø) ⬆️
...lib/accessibility/Behaviors/Embed/embedBehavior.ts 100% <100%> (ø)
packages/react/src/lib/accessibility/index.ts 100% <100%> (ø) ⬆️
packages/react/src/themes/teams/componentStyles.ts 100% <100%> (ø) ⬆️
...rc/themes/teams/components/Video/videoVariables.ts 100% <100%> (ø)
...t/src/themes/teams/components/Video/videoStyles.ts 33.33% <33.33%> (ø)
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d37c616...dae16b9. Read the comment docs.

}

export interface EmbedState {
active: boolean
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's add onActiveChanged prop for this component, and invoke it when we change the active prop, as it will be required when we want to use it in controlled mode (see for example the onOpenChanged in the Popup component)

Copy link
Member

Choose a reason for hiding this comment

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

Implemented as onActiveChanged, however I want address an inconsistency there separately because Popup has onOpenChange (without d on end).

Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect the d in the end, but agree, let's address in a separate PR, to avoid unnecessary breaking changes.


static defaultProps = {
as: 'video',
accessibility: defaultBehavior as Accessibility,
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for this, as the defaultBehavior will be applied if nothing is provided here.

Copy link
Member

@layershifter layershifter Apr 10, 2019

Choose a reason for hiding this comment

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

We have currently an assertion for this, going to address it in a separate PR.

e.stopPropagation()
e.preventDefault()

this.trySetState({ active: !this.state.active })
Copy link
Contributor

Choose a reason for hiding this comment

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

This is where we would invoke the onActiveChanged method.

Copy link
Collaborator

@bmdalex bmdalex left a comment

Choose a reason for hiding this comment

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

great work, no more comments on top of the ones from existing reviewers, pls address them before merge

}
},
control: ({ props: p, variables: v }): ICSSInJSStyle => ({
background: `0 no-repeat rgba(0,0,0,.25)`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please let's use colors values in the variables, so that we may override those in different themes.

Copy link
Contributor

@mnajdova mnajdova left a comment

Choose a reason for hiding this comment

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

One last comment. LGTM 👍

@layershifter layershifter merged commit 14a88fa into microsoft:master Apr 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants