Website: add page buttons to <scrollable-tweets> component (#16683)

Closes: #16304

Changes:
- Added page buttons to the `<scrollable-tweets>` component
This commit is contained in:
Eric 2024-02-14 17:31:51 -06:00 committed by GitHub
parent 88da536110
commit 96946763ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 119 additions and 57 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -23,16 +23,16 @@ parasails.registerComponent('scrollableTweets', {
return {
quotesToDisplay: [],
quotesWithVideoLinks: [],
currentTweetPage: 0,
numberOfTweetCards: 0,
numberOfTweetPages: 0,
tweetsDiv: undefined,
tweetCards: undefined,
pageWidth: undefined,
numberOfTweetCardsDisplayedOnThisPage: undefined,
showPreviousPageButton: false,
showNextPageButton: true,
numberOfTweetsPerPage: 0,
tweetCardWidth: 0,
tweetPageWidth: 0,
screenSize: 0,
scrolledAmount: 0,
scrollableAmount: 0,
modal: ''
syncing: false,
firstCardPosition: 0,
modal: '',
};
},
@ -41,7 +41,10 @@ parasails.registerComponent('scrollableTweets', {
// ╩ ╩ ╩ ╩ ╩╩═╝
template: `
<div class="d-flex flex-column">
<div purpose="tweets" class="d-flex flex-row flex-nowrap">
<div purpose="previous-page-indicator" @click="clickPreviousPage()" v-if="showPreviousPageButton"><img src="/images/testimonials-pagination-previous-48x48@2x.png"></div>
<div purpose="next-page-indicator" @click="clickNextPage()" v-if="showNextPageButton"><img src="/images/testimonials-pagination-next-48x48@2x.png"></div>
<a purpose="tweet-card" class="card" v-for="testimonial in quotesToDisplay" target="_blank" :href="testimonial.quoteLinkUrl">
<div purpose="logo" class="mb-4">
<img :height="testimonial.imageHeight" v-if="testimonial.quoteImageFilename" :src="'/images/'+testimonial.quoteImageFilename"/>
@ -61,11 +64,9 @@ parasails.registerComponent('scrollableTweets', {
</div>
</a>
</div>
<div purpose="page-indictator-container" class="mx-auto d-flex flex-row justify-content-center">
</div>
<div v-for="video in quotesWithVideoLinks">
<modal purpose="video-modal" v-if="modal === video.modalId" @close="closeModal()" >
<iframe width="560" height="315" :src="'https://www.youtube.com/embed/'+video.embedId+'?rel=0'" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe width="560" height="315" :src="'https://www.youtube.com/embed/'+video.embedId+'?rel=0'" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture;" allowfullscreen></iframe>
</modal>
</div>
</div>
@ -93,7 +94,13 @@ parasails.registerComponent('scrollableTweets', {
},
mounted: async function(){
this.tweetsDiv = $('div[purpose="tweets"]')[0];
this.tweetCards = $('a[purpose="tweet-card"]');
this.firstCardPosition = this.tweetCards[0].getBoundingClientRect().x;
this.numberOfTweetCardsDisplayedOnThisPage = this.tweetCards.length;
this.calculateHowManyFullTweetsCanBeDisplayed();
$(window).on('resize', this.calculateHowManyFullTweetsCanBeDisplayed);
$(window).on('wheel', this.updatePageIndicators);
},
beforeDestroy: function() {
@ -103,6 +110,46 @@ parasails.registerComponent('scrollableTweets', {
// ║║║║ ║ ║╣ ╠╦╝╠═╣║ ║ ║║ ║║║║╚═╗
// ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝
methods: {
calculateHowManyFullTweetsCanBeDisplayed: function() {
let firstTweetCard = this.tweetCards[0];
let nextTweetCard = this.tweetCards[1];
this.tweetCardWidth = nextTweetCard.getBoundingClientRect().x - firstTweetCard.getBoundingClientRect().x;
this.numberOfTweetsPerPage = Math.floor((document.body.clientWidth - this.firstCardPosition)/this.tweetCardWidth);
if(this.numberOfTweetsPerPage < 1){
this.numberOfTweetsPerPage = 1;
}
this.pageWidth = this.tweetCardWidth * this.numberOfTweetsPerPage;
if(this.numberOfTweetsPerPage >= this.numberOfTweetCardsDisplayedOnThisPage){
$(this.tweetsDiv).addClass('mx-auto');
} else {
$(this.tweetsDiv).removeClass('mx-auto');
}
this.updatePageIndicators();
},
clickNextPage: async function() {
if(!this.syncing){
this.tweetsDiv.scrollLeft += this.pageWidth;
await setTimeout(()=>{
this.updatePageIndicators();
}, 600);
}
},
clickPreviousPage: async function() {
if(!this.syncing){
this.tweetsDiv.scrollLeft -= this.pageWidth;
await setTimeout(()=>{
this.updatePageIndicators();
}, 600);
}
},
updatePageIndicators: function() {
this.syncing = false;
this.showPreviousPageButton = this.tweetsDiv.scrollLeft > (this.firstCardPosition * 0.5);
this.showNextPageButton = (this.tweetsDiv.scrollWidth - this.tweetsDiv.scrollLeft - this.tweetsDiv.clientWidth) >= this.tweetCardWidth * .25;
},
clickOpenVideoModal: function(modalName) {
this.modal = _.kebabCase(modalName);

View File

@ -9,24 +9,73 @@
font-size: 13px;
line-height: 20px;
position: relative;
[purpose='tweets']::-webkit-scrollbar {
display: none;
}
[purpose='previous-page-indicator'] {
display: none;
opacity: 0;
cursor: pointer;
z-index: 30;
position: absolute;
transition: transform 1s, opacity 0.25s ease-in;
transform: scale(0.5);
bottom: 50%;
left: 10px;
width: 48px;
height: 48px;
img {
width: 48px;
height: 48px;
}
}
[purpose='next-page-indicator'] {
display: none;
opacity: 0;
cursor: pointer;
position: absolute;
transition: transform 1s, opacity 0.25s ease-in;
transform: scale(0.5);
bottom: 50%;
z-index: 30;
right: 10px;
width: 48px;
height: 48px;
img {
width: 48px;
height: 48px;
}
}
[purpose='tweets'] {
overflow-x: scroll;
scroll-behavior: smooth;
padding-left: 120px;
padding-right: 120px;
margin-top: 80px;
padding-bottom: 16px;
margin-bottom: 80px;
scrollbar-width: none;
-ms-overflow-style: none;
&:hover {
[purpose='previous-page-indicator'] {
opacity: 1;
transform: scale(1.0);
}
[purpose='next-page-indicator'] {
opacity: 1;
transform: scale(1.0);
}
}
}
[purpose='tweet-card'] {
box-shadow: none;
background-color: #FFF;
[purpose='logo'] {
img {
max-height: 32px;
@ -78,33 +127,6 @@
box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.1);
}
}
[purpose='page-indictator-container'] {
margin-bottom: 80px;
padding-left: 120px;
padding-right: 120px;
}
[purpose='page-indicator'] {
cursor: pointer;
padding: 4px;
height: 16px;
width: 16px;
border-radius: 100%;
margin-right: 8px;
background-color: @core-vibrant-blue-15;
&.selected {
background-color: @core-fleet-black-50;
}
}
[purpose='tweets-page-indicator'] {
li {
}
li.selected {
}
}
[purpose='video-modal'] {
[purpose='modal-dialog'] {
width: 100%;
@ -139,15 +161,20 @@
}
@media(hover) {
[purpose='previous-page-indicator'] {
display: flex;
}
[purpose='next-page-indicator'] {
display: flex;
}
}
@media (max-width: 991px) {
[purpose='tweets'] {
padding-left: 80px;
padding-right: 80px;
}
[purpose='page-indictator-container'] {
padding-left: 80px;
padding-right: 80px;
}
}
@media (max-width: 768px) {
@ -155,10 +182,6 @@
padding-left: 40px;
padding-right: 40px;
}
[purpose='page-indictator-container'] {
padding-left: 40px;
padding-right: 40px;
}
[purpose='video-modal'] {
[purpose='modal-dialog'] {
max-width: 97vw;
@ -179,19 +202,11 @@
padding-left: 20px;
padding-right: 20px;
}
[purpose='page-indictator-container'] {
padding-left: 20px;
padding-right: 20px;
}
[purpose='tweet-card'] {
min-width: 280px;
padding: 20px;
border-radius: 16px;
}
[purpose='page-indicator'] {
padding: 12px;
margin-bottom: 8px;
}
[purpose='video-modal'] {
[purpose='modal-content'] {
width: 95vw;