Skip to content
Snippets Groups Projects
Commit 400e72d3 authored by Tuukka Turu's avatar Tuukka Turu
Browse files

Video component

parent a05afbab
No related branches found
No related tags found
No related merge requests found
......@@ -517,6 +517,69 @@ export namespace Components {
logoLabel?: string;
logoUrl?: string;
}
interface HyVideo {
/**
* Context label
*/
contextLabel: string;
/**
* Should context label be visible
*/
contextLabelVisible: boolean;
/**
* Date added date as string
*/
dateAdded: string;
/**
* Label for date added
*/
dateAddedLabel: string;
/**
* Duration number
*/
duration: string;
/**
* Label for duration number
*/
durationLabel: string;
headerstyle: string;
/**
* Use horizontal layout where metadata is on side
*/
horizontal: boolean;
/**
* Url to video, used with preview image
*/
linkToVideo: string;
/**
* Label for play button if preview image is provided
*/
playButtonLabel: string;
/**
* Should play button be visible
*/
playButtonVisible: boolean;
/**
* Preview image url
*/
previewImageUrl: string;
/**
* Video description
*/
videoDescription: string;
/**
* Video title
*/
videoTitle: string;
/**
* Views count number
*/
views: string;
/**
* Label for views number
*/
viewsLabel: string;
}
}
declare global {
interface HTMLColorBoxElement extends Components.ColorBox, HTMLStencilElement {}
......@@ -829,6 +892,11 @@ declare global {
prototype: HTMLHyUserLoginFormElement;
new (): HTMLHyUserLoginFormElement;
};
interface HTMLHyVideoElement extends Components.HyVideo, HTMLStencilElement {}
var HTMLHyVideoElement: {
prototype: HTMLHyVideoElement;
new (): HTMLHyVideoElement;
};
interface HTMLElementTagNameMap {
'color-box': HTMLColorBoxElement;
'hy-accordion-container': HTMLHyAccordionContainerElement;
......@@ -892,6 +960,7 @@ declare global {
'hy-tiny-text': HTMLHyTinyTextElement;
'hy-two-columns': HTMLHyTwoColumnsElement;
'hy-user-login-form': HTMLHyUserLoginFormElement;
'hy-video': HTMLHyVideoElement;
}
}
declare namespace LocalJSX {
......@@ -1376,6 +1445,69 @@ declare namespace LocalJSX {
logoLabel?: string;
logoUrl?: string;
}
interface HyVideo {
/**
* Context label
*/
contextLabel?: string;
/**
* Should context label be visible
*/
contextLabelVisible?: boolean;
/**
* Date added date as string
*/
dateAdded?: string;
/**
* Label for date added
*/
dateAddedLabel?: string;
/**
* Duration number
*/
duration?: string;
/**
* Label for duration number
*/
durationLabel?: string;
headerstyle?: string;
/**
* Use horizontal layout where metadata is on side
*/
horizontal?: boolean;
/**
* Url to video, used with preview image
*/
linkToVideo?: string;
/**
* Label for play button if preview image is provided
*/
playButtonLabel?: string;
/**
* Should play button be visible
*/
playButtonVisible?: boolean;
/**
* Preview image url
*/
previewImageUrl?: string;
/**
* Video description
*/
videoDescription?: string;
/**
* Video title
*/
videoTitle?: string;
/**
* Views count number
*/
views?: string;
/**
* Label for views number
*/
viewsLabel?: string;
}
interface IntrinsicElements {
'color-box': ColorBox;
'hy-accordion-container': HyAccordionContainer;
......@@ -1439,6 +1571,7 @@ declare namespace LocalJSX {
'hy-tiny-text': HyTinyText;
'hy-two-columns': HyTwoColumns;
'hy-user-login-form': HyUserLoginForm;
'hy-video': HyVideo;
}
}
export {LocalJSX as JSX};
......@@ -1511,6 +1644,7 @@ declare module '@stencil/core' {
'hy-tiny-text': LocalJSX.HyTinyText & JSXBase.HTMLAttributes<HTMLHyTinyTextElement>;
'hy-two-columns': LocalJSX.HyTwoColumns & JSXBase.HTMLAttributes<HTMLHyTwoColumnsElement>;
'hy-user-login-form': LocalJSX.HyUserLoginForm & JSXBase.HTMLAttributes<HTMLHyUserLoginFormElement>;
'hy-video': LocalJSX.HyVideo & JSXBase.HTMLAttributes<HTMLHyVideoElement>;
}
}
}
......@@ -104,6 +104,7 @@ Provide heading attribute for the component to choose what type of heading to us
- [hy-introduction](../hy-introduction)
- [hy-large-process-flow](../hy-large-process-flow)
- [hy-shortcuts](../hy-shortcuts)
- [hy-video](../hy-video)
### Graph
......@@ -115,6 +116,7 @@ graph TD;
hy-introduction --> hy-heading
hy-large-process-flow --> hy-heading
hy-shortcuts --> hy-heading
hy-video --> hy-heading
style hy-heading fill:#f9f,stroke:#333,stroke-width:4px
```
......
:host {
display: block;
}
.hy-video__video-container {
display: inline-block;
margin-bottom: 8px;
position: relative;
width: 100%;
@include breakpoint($wide) {
margin-bottom: 16px;
}
iframe {
height: 100%;
overflow: hidden;
width: 100%;
}
.hy-video__preview-image {
height: 100%;
left: 0;
object-fit: cover;
position: absolute;
top: 0;
width: 100%;
}
.hy-video__play {
left: 50%;
position: absolute;
top: 50%;
transform: translateX(-50%) translateY(-50%);
button {
align-items: center;
background: transparent;
border: none;
display: flex;
flex-direction: column;
&:hover {
cursor: pointer;
}
}
button .hy-video__button-label {
@include font-size(16px, 24px);
color: var(--grayscale-white);
font-family: var(--main-font-family);
font-weight: bold;
letter-spacing: -0.1px;
text-align: center;
text-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
text-transform: uppercase;
@include breakpoint($medium) {
@include font-size(24px, 32px);
letter-spacing: -0.14px;
text-shadow: 0 0 16px rgba(0, 0, 0, 0.6);
}
@include breakpoint($extrawide) {
@include font-size(28px, 32px);
letter-spacing: -0.16px;
}
@include breakpoint($overwide) {
@include font-size(32px, 32px);
}
}
button svg {
fill: var(--grayscale-white);
filter: drop-shadow(0 0 8px rgba(0, 0, 0, 0.6));
height: 48px;
width: 48px;
@include breakpoint($medium) {
filter: drop-shadow(0 0 16px rgba(0, 0, 0, 0.6));
height: 60px;
width: 60px;
}
@include breakpoint($wide) {
height: 80px;
width: 80px;
}
@include breakpoint($extrawide) {
height: 104px;
width: 104px;
}
@include breakpoint($overwide) {
height: 120px;
width: 120px;
}
}
}
> *:not(.hy-video__label):not(.hy-video__play) {
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
}
&:after {
content: '';
display: block;
// 16:9 ratio
padding-top: (9 / 16) * 100%;
}
}
.hy-video:not(.hy-video--horizontal) {
display: flex;
flex-direction: column;
.hy-video__meta__description {
@include breakpoint($wide) {
width: 57.24%;
}
}
}
.hy-video__label {
// font: h5 small size
@include font-size(16px, 20px);
background-color: var(--grayscale-black);
bottom: 12px;
color: var(--grayscale-white);
font-family: var(--main-font-family);
font-weight: bold;
left: -8px;
letter-spacing: -0.5px;
max-width: 46%; // 5.5 columns
padding: 6px 12px;
position: absolute;
text-transform: uppercase;
@include breakpoint($narrow) {
// >=480px
// font: h4 small size
@include font-size(18px, 24px);
bottom: 20px;
left: -16px;
letter-spacing: -0.56px;
max-width: 58%; // 7 columns
padding: 12px 24px;
position: absolute;
}
@include breakpoint($wide) {
// Applies both to 960px-1200px and 1201-1440px
// font: h4 medium size
@include font-size(22px, 28px);
bottom: 24px;
left: -16px;
letter-spacing: -0.69px;
padding: 16px 24px;
position: absolute;
}
@include breakpoint($overwide) {
// >= 1441px
// font: h3 medium size
@include font-size(26px, 32px);
bottom: 28px;
left: -16px;
letter-spacing: -0.8px;
padding: 20px 24px;
position: absolute;
}
}
.hy-video.hy-video--horizontal {
display: flex;
flex-direction: column;
justify-content: space-between;
@include breakpoint($wide) {
flex-direction: row;
}
.hy-video__meta {
padding-left: 0;
width: 100%;
@include breakpoint($wide) {
padding-left: 2.5%;
width: 57.24%;
}
}
}
.hy-video__meta__title {
h2.hy-heading {
margin: 8px 0 12px 0 !important;
padding: 0 !important;
@include breakpoint($wide) {
margin: 0 0 16px 0 !important;
}
}
}
.hy-video__meta__details {
display: flex;
flex-direction: row;
margin-bottom: 12px;
@include breakpoint($wide) {
margin-bottom: 16px;
}
}
.hy-video__meta__details--item {
border-right: 1px dashed var(--brand-main-light);
display: flex;
flex-direction: column;
margin-right: 44px;
min-width: 87px;
padding-right: 46px;
place-content: center space-between;
&:last-child {
border-right: 0;
}
}
.hy-video__meta__description {
@include font-size(14px, 20px);
color: var(--grayscale-dark);
display: block;
font-family: var(--main-font-family);
letter-spacing: 0;
margin-bottom: 16px;
width: 100%;
@include breakpoint($medium) {
@include font-size(16px, 24px);
}
}
.hy-video__meta__label {
font-weight: 700;
}
.hy-video__meta__label,
.hy-video__meta__content {
@include font-size(16px, 20px);
color: var(--grayscale-black);
font-family: var(--main-font-family);
letter-spacing: -0.5px;
@include breakpoint($medium) {
@include font-size(18px, 24px);
letter-spacing: -0.56px;
}
@include breakpoint($extrawide) {
@include font-size(22px, 34px);
letter-spacing: -0.69px;
}
}
import {Component, Prop, h, Element} from '@stencil/core';
import {HeadingVarians} from '../../utils/utils';
@Component({
tag: 'hy-video',
styleUrl: 'hy-video.scss',
shadow: false,
})
export class HyVideo {
@Element() el: HTMLElement;
/** Video title */
@Prop() videoTitle: string;
/** Video description */
@Prop() videoDescription: string;
/** Context label */
@Prop() contextLabel: string;
/** Should context label be visible */
@Prop() contextLabelVisible: boolean = false;
/** Preview image url */
@Prop() previewImageUrl: string;
/** Url to video, used with preview image */
@Prop() linkToVideo: string;
/** Label for play button if preview image is provided */
@Prop() playButtonLabel: string;
/** Should play button be visible */
@Prop() playButtonVisible: boolean = false;
/** Views count number */
@Prop() views: string;
/** Label for views number */
@Prop() viewsLabel: string;
/** Duration number */
@Prop() duration: string;
/** Label for duration number */
@Prop() durationLabel: string;
/** Date added date as string */
@Prop() dateAdded: string;
/** Label for date added */
@Prop() dateAddedLabel: string;
/** Use horizontal layout where metadata is on side */
@Prop() horizontal: boolean = false;
@Prop() headerstyle: string = 'with-sidebar';
renderPreviewWithLink = () => {
return this.linkToVideo ? (
<a title={this.videoTitle} href={this.linkToVideo} class="hy-video__link-to-video">
<img class="hy-video__preview-image" src={this.previewImageUrl} alt={this.videoTitle} />
</a>
) : (
<img class="hy-video__preview-image" src={this.previewImageUrl} alt={this.videoTitle} />
);
};
renderPlayButton = () => {
return (
<span class="hy-video__play">
<button type="button">
<hy-icon icon={'hy-icon-video'} class={'hy-video__play-icon'} size={20} />
<span class="hy-video__button-label">{this.playButtonLabel}</span>
</button>
</span>
);
};
render() {
const classAttributes = [
'hy-video',
this.horizontal ? 'hy-video--horizontal' : '',
`hy-video--${this.headerstyle}`,
].join(' ');
return (
<div class={classAttributes}>
<div class="hy-video__video-container">
{this.previewImageUrl ? (
<div>
{this.renderPreviewWithLink()}
<slot name="video"></slot>
</div>
) : (
<slot name="video"></slot>
)}
{this.playButtonVisible && this.renderPlayButton()}
{this.contextLabelVisible && <span class="hy-video__label">{this.contextLabel}</span>}
</div>
<div class="hy-video__meta">
{this.videoTitle && (
<hy-heading class="hy-video__meta__title" heading={HeadingVarians.h2}>
{this.videoTitle}
</hy-heading>
)}
{(this.duration || this.views || this.dateAdded) && (
<div class="hy-video__meta__details">
{this.duration && (
<div class="hy-video__meta__details--item">
<span class="hy-video__meta__label">{this.durationLabel}</span>
<span class="hy-video__meta__content">{this.duration}</span>
</div>
)}
{this.views && (
<div class="hy-video__meta__details--item">
<span class="hy-video__meta__label">{this.viewsLabel}</span>
<span class="hy-video__meta__content">{this.views}</span>
</div>
)}
{this.dateAdded && (
<div class="hy-video__meta__details--item">
<span class="hy-video__meta__label">{this.dateAddedLabel}</span>
<span class="hy-video__meta__content">{this.dateAdded}</span>
</div>
)}
</div>
)}
{this.videoDescription && (
<hy-paragraph-text class="hy-video__meta__description">{this.videoDescription}</hy-paragraph-text>
)}
</div>
</div>
);
}
}
# hy-video
<!-- Auto Generated Below -->
## Properties
| Property | Attribute | Description | Type | Default |
| --------------------- | ----------------------- | -------------------------------------------------- | --------- | ---------------- |
| `contextLabel` | `context-label` | Context label | `string` | `undefined` |
| `contextLabelVisible` | `context-label-visible` | Should context label be visible | `boolean` | `false` |
| `dateAdded` | `date-added` | Date added date as string | `string` | `undefined` |
| `dateAddedLabel` | `date-added-label` | Label for date added | `string` | `undefined` |
| `duration` | `duration` | Duration number | `string` | `undefined` |
| `durationLabel` | `duration-label` | Label for duration number | `string` | `undefined` |
| `headerstyle` | `headerstyle` | | `string` | `'with-sidebar'` |
| `horizontal` | `horizontal` | Use horizontal layout where metadata is on side | `boolean` | `false` |
| `linkToVideo` | `link-to-video` | Url to video, used with preview image | `string` | `undefined` |
| `playButtonLabel` | `play-button-label` | Label for play button if preview image is provided | `string` | `undefined` |
| `playButtonVisible` | `play-button-visible` | Should play button be visible | `boolean` | `false` |
| `previewImageUrl` | `preview-image-url` | Preview image url | `string` | `undefined` |
| `videoDescription` | `video-description` | Video description | `string` | `undefined` |
| `videoTitle` | `video-title` | Video title | `string` | `undefined` |
| `views` | `views` | Views count number | `string` | `undefined` |
| `viewsLabel` | `views-label` | Label for views number | `string` | `undefined` |
## Dependencies
### Depends on
- [hy-icon](../icon)
- [hy-heading](../heading)
- [hy-paragraph-text](../paragraph-text)
### Graph
```mermaid
graph TD;
hy-video --> hy-icon
hy-video --> hy-heading
hy-video --> hy-paragraph-text
style hy-video fill:#f9f,stroke:#333,stroke-width:4px
```
---
Helsinki University Design System
......@@ -23,6 +23,8 @@ const iconNames: IconName = {
'hy-icon-quote': (p) => <icons.IconQuote {...p} />,
'hy-icon-remove': (p) => <icons.Remove {...p} />,
'hy-icon-search': (p) => <icons.Search {...p} />,
'hy-icon-play': (p) => <icons.Play {...p} />,
'hy-icon-video': (p) => <icons.Video {...p} />,
'hy-icon-some-facebook': (p) => <icons.SomeFacebook {...p} />,
'hy-icon-some-instagram': (p) => <icons.SomeInstagram {...p} />,
'hy-icon-some-youtube': (p) => <icons.SomeYoutube {...p} />,
......
......@@ -34,6 +34,7 @@
- [hy-site-logo](../site-header/site-logo)
- [hy-site-search](../site-header/site-search)
- [hy-tabs](../hy-tabs)
- [hy-video](../hy-video)
### Graph
......@@ -59,6 +60,7 @@ graph TD;
hy-site-logo --> hy-icon
hy-site-search --> hy-icon
hy-tabs --> hy-icon
hy-video --> hy-icon
style hy-icon fill:#f9f,stroke:#333,stroke-width:4px
```
......
......@@ -36,6 +36,20 @@ Basic text paragraph.
| `headerstyle` | `headerstyle` | | `string` | `'default'` |
| `variant` | `variant` | | `string` | `undefined` |
## Dependencies
### Used by
- [hy-video](../hy-video)
### Graph
```mermaid
graph TD;
hy-video --> hy-paragraph-text
style hy-paragraph-text fill:#f9f,stroke:#333,stroke-width:4px
```
---
Helsinki University Design System
......@@ -186,6 +186,62 @@
sc-label="List of conferences"
>
</hy-banner>
<hy-video
video-title="Youtube test embed"
video-description="Video description for giving more context to what the user is viewing (eg. if the video is part of a lecture series, or a series of speeches). Can include links and probably needs to have a character limit."
context-label="Youtube test"
views="123"
views-label="Views"
duration="1:23"
duration-label="Duration"
date-added="28.10.2020"
date-added-label="Added"
play-button-visible
context-label-visible
play-button-label="Play video"
preview-image-url="https://www.helsinki.fi/sites/default/files/styles/16_9_huge/public/kukkataedit_ja_-sedaet-6_0.jpg"
>
<iframe
slot="video"
src="https://www.youtube.com/embed/Bsycp5I2Vy8?width=&height=&theme=dark&autoplay=0&vq=hd720&rel=0&showinfo=1&modestbranding=0&iv_load_policy=1&controls=1&autohide=2&wmode=opaque"
frameborder="0"
></iframe>
</hy-video>
<hy-video
horizontal
video-title="Youtube test embed"
video-description="Video description for giving more context to what the user is viewing (eg. if the video is part of a lecture series, or a series of speeches). Can include links and probably needs to have a character limit."
context-label="Youtube test"
views="123"
views-label="Views"
duration="1:23"
context-label-visible
duration-label="Duration"
date-added="28.10.2020"
date-added-label="Added"
>
<iframe
slot="video"
src="https://www.youtube.com/embed/Bsycp5I2Vy8?width=&height=&theme=dark&autoplay=0&vq=hd720&rel=0&showinfo=1&modestbranding=0&iv_load_policy=1&controls=1&autohide=2&wmode=opaque"
frameborder="0"
></iframe>
</hy-video>
<hy-video
context-label="Youtube test"
play-button-visible
context-label-visible
play-button-label="Play video"
link-to-video="https://www.google.com"
preview-image-url="https://www.helsinki.fi/sites/default/files/styles/16_9_huge/public/kukkataedit_ja_-sedaet-6_0.jpg"
>
</hy-video>
<hy-video>
<iframe
slot="video"
src="https://www.youtube.com/embed/Bsycp5I2Vy8?width=&height=&theme=dark&autoplay=0&vq=hd720&rel=0&showinfo=1&modestbranding=0&iv_load_policy=1&controls=1&autohide=2&wmode=opaque"
frameborder="0"
></iframe>
</hy-video>
<hy-accordion-container accordionid="example-accordion">
<hy-accordion-item accordiontitle="This is a accordion item 1">
<hy-paragraph-text>Accordion content</hy-paragraph-text>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment