kopia lustrzana https://github.com/shoelace-style/shoelace
add responsive media component; fixes #436
rodzic
86fc6b85d6
commit
5c619b87b6
|
|
@ -38,7 +38,6 @@
|
|||
- [Radio Group](/components/radio-group.md)
|
||||
- [Range](/components/range.md)
|
||||
- [Rating](/components/rating.md)
|
||||
- [Responsive Embed](/components/responsive-embed.md)
|
||||
- [Select](/components/select.md)
|
||||
- [Skeleton](/components/skeleton.md)
|
||||
- [Spinner](/components/spinner.md)
|
||||
|
|
@ -59,6 +58,7 @@
|
|||
- [QR Code](/components/qr-code.md)
|
||||
- [Relative Time](/components/relative-time.md)
|
||||
- [Resize Observer](/components/resize-observer.md)
|
||||
- [Responsive Media](/components/responsive-media.md)
|
||||
|
||||
- Design Tokens
|
||||
- [Typography](/tokens/typography.md)
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
# 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]
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# Responsive Media
|
||||
|
||||
[component-header:sl-responsive-media]
|
||||
|
||||
Displays media in the desired aspect ratio.
|
||||
|
||||
You can slot in any [replaced element](https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element), including `<iframe>`, `<img>`, and `<video>`. As the element's width changes, its height will resize proportionally. Only one element should be slotted into the container. The default aspect ratio is `16:9`.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-media>
|
||||
<img src="https://images.unsplash.com/photo-1541427468627-a89a96e5ca1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1800&q=80" alt="A train riding through autumn foliage with mountains in the distance.">
|
||||
</sl-responsive-media>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Responsive Images
|
||||
|
||||
The following image maintains a `4:3` aspect ratio as its container is resized.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-media aspect-ratio="4:3">
|
||||
<img src="https://images.unsplash.com/photo-1473186578172-c141e6798cf4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1800&q=80" alt="Two blue chairs on a sandy beach.">
|
||||
</sl-responsive-media>
|
||||
```
|
||||
|
||||
### Responsive Videos
|
||||
|
||||
The following video is embedded using an `iframe` and maintains a `16:9` aspect ratio as its container is resized.
|
||||
|
||||
```html preview
|
||||
<sl-responsive-media aspect-ratio="16:9">
|
||||
<iframe src="https://player.vimeo.com/video/1053647?title=0&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
|
||||
</sl-responsive-media>
|
||||
```
|
||||
|
||||
[component-metadata:sl-responsive-media]
|
||||
|
|
@ -8,6 +8,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
|||
|
||||
## Next
|
||||
|
||||
- 🚨 BREAKING: renamed `sl-responsive-embed` to `sl-responsive-media` and added support for images and videos [#436](https://github.com/shoelace-style/shoelace/issues/436)
|
||||
- Fixed a bug where setting properties before an element was defined would render incorrectly [#425](https://github.com/shoelace-style/shoelace/issues/425)
|
||||
- Fixed a bug that caused all modules to be imported when cherry picking certain components [#439](https://github.com/shoelace-style/shoelace/issues/439)
|
||||
- Improved a11y in `sl-progress-ring`
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
@use '../../styles/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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
import { LitElement, html, unsafeCSS } from 'lit';
|
||||
import { customElement, property, query } from 'lit/decorators';
|
||||
import { watch } from '../../internal/decorators';
|
||||
import styles from 'sass:./responsive-embed.scss';
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
* @status stable
|
||||
*
|
||||
* @part base - The component's base wrapper.
|
||||
*/
|
||||
@customElement('sl-responsive-embed')
|
||||
export default class SlResponsiveEmbed extends LitElement {
|
||||
static styles = unsafeCSS(styles);
|
||||
|
||||
@query('.responsive-embed') 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.
|
||||
*/
|
||||
@property({ attribute: 'aspect-ratio' }) aspectRatio = '16:9';
|
||||
|
||||
@watch('aspectRatio')
|
||||
updateAspectRatio() {
|
||||
const split = this.aspectRatio.split(':');
|
||||
const x = parseInt(split[0]);
|
||||
const y = parseInt(split[1]);
|
||||
|
||||
this.base.style.paddingBottom = x && y ? `${(y / x) * 100}%` : '';
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div part="base" class="responsive-embed">
|
||||
<slot @slotchange=${() => this.updateAspectRatio()}></slot>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'sl-responsive-embed': SlResponsiveEmbed;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
@use '../../styles/component';
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.responsive-media {
|
||||
position: relative;
|
||||
|
||||
::slotted(*) {
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.responsive-media--cover {
|
||||
::slotted(embed),
|
||||
::slotted(iframe),
|
||||
::slotted(img),
|
||||
::slotted(video) {
|
||||
object-fit: cover !important;
|
||||
}
|
||||
}
|
||||
|
||||
.responsive-media--contain {
|
||||
::slotted(embed),
|
||||
::slotted(iframe),
|
||||
::slotted(img),
|
||||
::slotted(video) {
|
||||
object-fit: contain !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { LitElement, html, unsafeCSS } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators';
|
||||
import { classMap } from 'lit-html/directives/class-map';
|
||||
import styles from 'sass:./responsive-media.scss';
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
* @status stable
|
||||
*
|
||||
* @slot - The element to receive the aspect ratio. Should be a replaced element, such as `<img>`, `<iframe>`, or `<video>`.
|
||||
*/
|
||||
@customElement('sl-responsive-media')
|
||||
export default class SlResponsiveMedia extends LitElement {
|
||||
static styles = unsafeCSS(styles);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@property({ attribute: 'aspect-ratio' }) aspectRatio = '16:9';
|
||||
|
||||
/** Determines how content will be resized to fit its container. */
|
||||
@property() fit: 'cover' | 'contain' = 'cover';
|
||||
|
||||
render() {
|
||||
const split = this.aspectRatio.split(':');
|
||||
const x = parseInt(split[0]);
|
||||
const y = parseInt(split[1]);
|
||||
const paddingBottom = x && y ? `${(y / x) * 100}%` : '0';
|
||||
|
||||
return html`
|
||||
<div
|
||||
class=${classMap({
|
||||
'responsive-media': true,
|
||||
'responsive-media--cover': this.fit === 'cover',
|
||||
'responsive-media--contain': this.fit === 'contain'
|
||||
})}
|
||||
style="padding-bottom: ${paddingBottom}"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'sl-responsive-media': SlResponsiveMedia;
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ export { default as SlRange } from './components/range/range';
|
|||
export { default as SlRating } from './components/rating/rating';
|
||||
export { default as SlRelativeTime } from './components/relative-time/relative-time';
|
||||
export { default as SlResizeObserver } from './components/resize-observer/resize-observer';
|
||||
export { default as SlResponsiveEmbed } from './components/responsive-embed/responsive-embed';
|
||||
export { default as SlResponsiveMedia } from './components/responsive-media/responsive-media';
|
||||
export { default as SlSelect } from './components/select/select';
|
||||
export { default as SlSkeleton } from './components/skeleton/skeleton';
|
||||
export { default as SlSpinner } from './components/spinner/spinner';
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue