Add responsive embed utility component

pull/200/head
Cory LaViska 2020-08-31 16:47:31 -04:00
rodzic e361a5cad7
commit 215ea51a26
5 zmienionych plików z 121 dodań i 3 usunięć

Wyświetl plik

@ -1,5 +1,4 @@
- Getting Started
- [Overview](/)
- [Installation](/getting-started/installation.md)
- [Usage](/getting-started/usage.md)
@ -9,9 +8,7 @@
- [Community](/getting-started/community.md)
- Components
- [Alert](/components/alert.md)
- [Animation](/components/animation.md)
- [Avatar](/components/avatar.md)
- [Badge](/components/badge.md)
- [Button](/components/button.md)
@ -49,7 +46,9 @@
- [Tooltip](/components/tooltip.md)
- Utility Components
- [Animation](/components/animation.md)
- [Format Bytes](/components/format-bytes.md)
- [Responsive Embed](/components/responsive-embed.md)
- Design Tokens
- [Typography](/tokens/typography.md)

Wyświetl plik

@ -0,0 +1,27 @@
# Responsive Embed
[component-header:sl-responsive-embed]
Displays embedded media in a responsive manner based on its aspect ratio.
You can embed any element of the `<iframe>`, `<embed>`, or `<object>` type. The default aspect ratio is `16:9`.
```html preview
<sl-responsive-embed>
<iframe src="https://player.vimeo.com/video/1053647?title=0&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
</sl-responsive-embed>
```
## Examples
### Aspect Ratio
To set the aspect ratio, use the `aspect-ratio` attribute.
```html preview
<sl-responsive-embed aspect-ratio="4:3">
<iframe src="https://www.youtube.com/embed/mM5_T-F1Yn4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</sl-responsive-embed>
```
[component-metadata:sl-responsive-embed]

21
src/components.d.ts vendored
Wyświetl plik

@ -785,6 +785,12 @@ export namespace Components {
*/
"value": number;
}
interface SlResponsiveEmbed {
/**
* The aspect ratio of the embedded media in the format of `width:height`, e.g. `16:9`, `4:3`, or `1:1`. Ratios not in this format will be ignored.
*/
"aspectRatio": string;
}
interface SlSelect {
/**
* Set to true to add a clear button when the select is populated.
@ -1282,6 +1288,12 @@ declare global {
prototype: HTMLSlRatingElement;
new (): HTMLSlRatingElement;
};
interface HTMLSlResponsiveEmbedElement extends Components.SlResponsiveEmbed, HTMLStencilElement {
}
var HTMLSlResponsiveEmbedElement: {
prototype: HTMLSlResponsiveEmbedElement;
new (): HTMLSlResponsiveEmbedElement;
};
interface HTMLSlSelectElement extends Components.SlSelect, HTMLStencilElement {
}
var HTMLSlSelectElement: {
@ -1371,6 +1383,7 @@ declare global {
"sl-radio": HTMLSlRadioElement;
"sl-range": HTMLSlRangeElement;
"sl-rating": HTMLSlRatingElement;
"sl-responsive-embed": HTMLSlResponsiveEmbedElement;
"sl-select": HTMLSlSelectElement;
"sl-skeleton": HTMLSlSkeletonElement;
"sl-spinner": HTMLSlSpinnerElement;
@ -2211,6 +2224,12 @@ declare namespace LocalJSX {
*/
"value"?: number;
}
interface SlResponsiveEmbed {
/**
* The aspect ratio of the embedded media in the format of `width:height`, e.g. `16:9`, `4:3`, or `1:1`. Ratios not in this format will be ignored.
*/
"aspectRatio"?: string;
}
interface SlSelect {
/**
* Set to true to add a clear button when the select is populated.
@ -2563,6 +2582,7 @@ declare namespace LocalJSX {
"sl-radio": SlRadio;
"sl-range": SlRange;
"sl-rating": SlRating;
"sl-responsive-embed": SlResponsiveEmbed;
"sl-select": SlSelect;
"sl-skeleton": SlSkeleton;
"sl-spinner": SlSpinner;
@ -2607,6 +2627,7 @@ declare module "@stencil/core" {
"sl-radio": LocalJSX.SlRadio & JSXBase.HTMLAttributes<HTMLSlRadioElement>;
"sl-range": LocalJSX.SlRange & JSXBase.HTMLAttributes<HTMLSlRangeElement>;
"sl-rating": LocalJSX.SlRating & JSXBase.HTMLAttributes<HTMLSlRatingElement>;
"sl-responsive-embed": LocalJSX.SlResponsiveEmbed & JSXBase.HTMLAttributes<HTMLSlResponsiveEmbedElement>;
"sl-select": LocalJSX.SlSelect & JSXBase.HTMLAttributes<HTMLSlSelectElement>;
"sl-skeleton": LocalJSX.SlSkeleton & JSXBase.HTMLAttributes<HTMLSlSkeletonElement>;
"sl-spinner": LocalJSX.SlSpinner & JSXBase.HTMLAttributes<HTMLSlSpinnerElement>;

Wyświetl plik

@ -0,0 +1,19 @@
@import 'component';
:host {
display: block;
}
.responsive-embed {
position: relative;
::slotted(embed),
::slotted(iframe),
::slotted(object) {
position: absolute !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
}
}

Wyświetl plik

@ -0,0 +1,52 @@
import { Component, Prop, Watch, h } from '@stencil/core';
/**
* @since 2.0
* @status stable
*
* @part base - The component's base wrapper.
*/
@Component({
tag: 'sl-responsive-embed',
styleUrl: 'responsive-embed.scss',
shadow: true
})
export class ResponsiveEmbed {
base: HTMLElement;
/**
* The aspect ratio of the embedded media in the format of `width:height`, e.g. `16:9`, `4:3`, or `1:1`. Ratios not in
* this format will be ignored.
*/
@Prop() aspectRatio = '16:9';
@Watch('aspectRatio')
handleAspectRatioChange() {
this.setAspectRatio();
}
connectedCallback() {
this.handleSlotChange = this.handleSlotChange.bind(this);
}
handleSlotChange() {
this.setAspectRatio();
}
setAspectRatio() {
const split = this.aspectRatio.split(':');
const x = parseInt(split[0]);
const y = parseInt(split[1]);
this.base.style.paddingBottom = x && y ? `${(y / x) * 100}%` : null;
}
render() {
return (
<div ref={el => (this.base = el)} part="base" class="responsive-embed">
<slot onSlotchange={this.handleSlotChange} />
</div>
);
}
}