diff --git a/all.js b/all.js index bc4175c..f3d9678 100644 --- a/all.js +++ b/all.js @@ -9,6 +9,8 @@ import './buttons/button.js' import './buttons/filled-tonal-button.js' import './buttons/outlined-button.js' import './buttons/text-button.js' +import './carousel/carousel.js' +import './carousel/carousel-item.js' import './checkbox/checkbox.js' import './chips/assist-chip.js' import './chips/chip-set.js' @@ -48,6 +50,8 @@ import './text/text-field.js' // LINT.IfChange(exports) // go/keep-sorted start export * from './buttons/button.js' +export * from './carousel/carousel.js' +export * from './carousel/carousel-item.js' export * from './checkbox/checkbox.js' export * from './chips/chip.js' export * from './chips/chip-set.js' diff --git a/carousel/carousel-item.js b/carousel/carousel-item.js new file mode 100644 index 0000000..5453787 --- /dev/null +++ b/carousel/carousel-item.js @@ -0,0 +1,44 @@ +import { html, LitElement, css } from 'lit'; + +/** + * An item inside a Material 3 Carousel. + * + * @element md-carousel-item + */ +export class CarouselItem extends LitElement { + static get styles() { + return [ + css` + :host { + display: block; + border-radius: 16px; + overflow: hidden; + /* Default aspect ratio, can be overridden */ + aspect-ratio: 1; + width: 200px; /* Default width, can be overridden */ + scroll-snap-align: start; + flex: 0 0 auto; + } + + ::slotted(img) { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + } + ` + ]; + } + + constructor() { + super(); + this.internals = this.attachInternals(); + this.internals.role = 'listitem'; + } + + render() { + return html``; + } +} + +customElements.define('md-carousel-item', CarouselItem); diff --git a/carousel/carousel.js b/carousel/carousel.js new file mode 100644 index 0000000..e1cb3c6 --- /dev/null +++ b/carousel/carousel.js @@ -0,0 +1,45 @@ +import { html, LitElement, css } from 'lit'; + +/** + * A Material 3 Carousel component. + * + * @element md-carousel + */ +export class Carousel extends LitElement { + static get styles() { + return [ + css` + :host { + display: flex; + overflow-x: auto; + scroll-snap-type: x mandatory; + gap: 8px; + padding: 16px; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE/Edge */ + } + + :host::-webkit-scrollbar { + display: none; /* Chrome/Safari/Opera */ + } + + ::slotted(*) { + scroll-snap-align: start; + flex: 0 0 auto; + } + ` + ]; + } + + constructor() { + super(); + this.internals = this.attachInternals(); + this.internals.role = 'list'; + } + + render() { + return html``; + } +} + +customElements.define('md-carousel', Carousel); diff --git a/common.js b/common.js index d063462..15f8797 100644 --- a/common.js +++ b/common.js @@ -7,6 +7,8 @@ * for production. */ import './buttons/button.js' +import './carousel/carousel.js' +import './carousel/carousel-item.js' import './checkbox/checkbox.js' import './chips/chip.js' import './chips/chip-set.js' @@ -27,6 +29,8 @@ import './tabs/tabs.js' import './text/text-field.js' export * from './buttons/button.js' +export * from './carousel/carousel.js' +export * from './carousel/carousel-item.js' export * from './checkbox/checkbox.js' export * from './chips/chip.js' export * from './chips/chip-set.js' diff --git a/demo/carousel.html b/demo/carousel.html new file mode 100644 index 0000000..1973f9b --- /dev/null +++ b/demo/carousel.html @@ -0,0 +1,83 @@ + + + + + + Material 3 Carousel Demo + + + + + + + + +
+

Material 3 Carousel

+ + + + Random image 1 + + + Random image 2 + + + Random image 3 + + + Random image 4 + + + Random image 5 + + + Random image 6 + + +
+ + diff --git a/demo/index.html b/demo/index.html index bb1a109..dbd0c47 100644 --- a/demo/index.html +++ b/demo/index.html @@ -149,6 +149,7 @@
Other demo pages: