Merge branch 'feature/home-org-carousel'
This commit is contained in:
commit
5014193484
2 changed files with 161 additions and 18 deletions
|
|
@ -401,11 +401,10 @@ describe('homepage sponsor strip', () => {
|
||||||
cy.visit('/')
|
cy.visit('/')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders the heading and all seven partner logos', () => {
|
it('renders the heading and all seven partner logos in a carousel', () => {
|
||||||
cy.get('[data-cy="sponsors"]').within(() => {
|
cy.get('[data-cy="sponsors"]').within(() => {
|
||||||
cy.contains('h2', 'Organizations Rabbi Gerzi has Worked With')
|
cy.contains('h2', 'Organizations Rabbi Gerzi has Worked With')
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
cy.get('[data-cy="sponsor-logo"]').should('have.length', 7)
|
|
||||||
const expectedAlts = [
|
const expectedAlts = [
|
||||||
'SHARE',
|
'SHARE',
|
||||||
'U of Israel',
|
'U of Israel',
|
||||||
|
|
@ -415,9 +414,67 @@ describe('homepage sponsor strip', () => {
|
||||||
'Aish HaTorah',
|
'Aish HaTorah',
|
||||||
'Yeshivat Lev HaTorah',
|
'Yeshivat Lev HaTorah',
|
||||||
]
|
]
|
||||||
|
cy.get('[data-cy="sponsor-logo"]').should('have.length', 7)
|
||||||
expectedAlts.forEach((altText) => {
|
expectedAlts.forEach((altText) => {
|
||||||
cy.get(`[data-cy="sponsor-logo"][alt="${altText}"]`)
|
cy.get(`[data-cy="sponsor-logo"][alt="${altText}"]`)
|
||||||
.should('be.visible')
|
.should('have.attr', 'src')
|
||||||
|
})
|
||||||
|
cy.get('[data-cy="sponsor-carousel"]').should('be.visible')
|
||||||
|
cy.get('[data-cy="sponsor-logo-duplicate"]')
|
||||||
|
.should('have.length', 7)
|
||||||
|
cy.get('[data-cy="sponsor-logo-duplicate"][alt=""]')
|
||||||
|
.should('have.length', 7)
|
||||||
|
cy.get('[data-cy="sponsor-logo-group-duplicate"]')
|
||||||
|
.should('have.attr', 'aria-hidden', 'true')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('centers the carousel with side buffers and edge fades', () => {
|
||||||
|
cy.viewport(1200, 900)
|
||||||
|
cy.get('[data-cy="sponsors"]').within(() => {
|
||||||
|
cy.get('[data-cy="sponsor-carousel"]').then((carouselElements) => {
|
||||||
|
const carouselElement = carouselElements[0]
|
||||||
|
const sponsorInnerElement = carouselElement.parentElement
|
||||||
|
|
||||||
|
if (sponsorInnerElement === null) {
|
||||||
|
throw new Error('Sponsor inner element is missing')
|
||||||
|
}
|
||||||
|
|
||||||
|
const carouselBounds = carouselElement.getBoundingClientRect()
|
||||||
|
const sponsorInnerBounds =
|
||||||
|
sponsorInnerElement.getBoundingClientRect()
|
||||||
|
const leftBuffer = carouselBounds.left - sponsorInnerBounds.left
|
||||||
|
const rightBuffer = sponsorInnerBounds.right - carouselBounds.right
|
||||||
|
const carouselRatio = carouselBounds.width / sponsorInnerBounds.width
|
||||||
|
const carouselStyle = getComputedStyle(carouselElement)
|
||||||
|
const maskImage =
|
||||||
|
carouselStyle.maskImage || carouselStyle.webkitMaskImage
|
||||||
|
|
||||||
|
expect(carouselRatio).to.be.closeTo(0.85, 0.02)
|
||||||
|
expect(leftBuffer).to.be.closeTo(rightBuffer, 1)
|
||||||
|
expect(maskImage).to.contain('50px')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uses the faster carousel timing', () => {
|
||||||
|
cy.get('[data-cy="sponsor-track"]').then((trackElements) => {
|
||||||
|
const trackStyle = getComputedStyle(trackElements[0])
|
||||||
|
|
||||||
|
expect(trackStyle.animationDuration).to.equal('20s')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('scrolls the sponsor logos from right to left', () => {
|
||||||
|
cy.get('[data-cy="sponsor-track"]').then((trackElements) => {
|
||||||
|
const startingLeft = trackElements[0].getBoundingClientRect().left
|
||||||
|
|
||||||
|
cy.wait(750)
|
||||||
|
cy.get('[data-cy="sponsor-track"]').then((laterTrackElements) => {
|
||||||
|
const laterLeft =
|
||||||
|
laterTrackElements[0].getBoundingClientRect().left
|
||||||
|
|
||||||
|
expect(startingLeft).to.be.greaterThan(laterLeft)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,32 @@ const sponsors: Sponsor[] = [
|
||||||
{ name: 'Yeshivat Lev HaTorah', src: '/assets/levhatorah.png' },
|
{ name: 'Yeshivat Lev HaTorah', src: '/assets/levhatorah.png' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const sponsorGroups: Sponsor[][] = [sponsors, sponsors]
|
||||||
|
|
||||||
|
function sponsorGroupDataCy(sponsorGroupIndex: number): string {
|
||||||
|
if (sponsorGroupIndex === 0) {
|
||||||
|
return 'sponsor-logo-group'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'sponsor-logo-group-duplicate'
|
||||||
|
}
|
||||||
|
|
||||||
|
function sponsorLogoAlt(sponsor: Sponsor, sponsorGroupIndex: number): string {
|
||||||
|
if (sponsorGroupIndex === 0) {
|
||||||
|
return sponsor.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function sponsorLogoDataCy(sponsorGroupIndex: number): string {
|
||||||
|
if (sponsorGroupIndex === 0) {
|
||||||
|
return 'sponsor-logo'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'sponsor-logo-duplicate'
|
||||||
|
}
|
||||||
|
|
||||||
interface Project {
|
interface Project {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
|
|
@ -363,17 +389,27 @@ const projects: Project[] = [
|
||||||
<section class="sponsors" data-cy="sponsors">
|
<section class="sponsors" data-cy="sponsors">
|
||||||
<div class="sponsors__inner">
|
<div class="sponsors__inner">
|
||||||
<h2 class="sponsors__heading">Organizations Rabbi Gerzi has Worked With</h2>
|
<h2 class="sponsors__heading">Organizations Rabbi Gerzi has Worked With</h2>
|
||||||
<div class="sponsors__row">
|
<div class="sponsors__carousel" data-cy="sponsor-carousel">
|
||||||
|
<div class="sponsors__track" data-cy="sponsor-track">
|
||||||
|
<div
|
||||||
|
v-for="(sponsorGroup, sponsorGroupIndex) in sponsorGroups"
|
||||||
|
:key="`sponsor-group-${sponsorGroupIndex}`"
|
||||||
|
class="sponsors__group"
|
||||||
|
:aria-hidden="sponsorGroupIndex === 1 ? 'true' : undefined"
|
||||||
|
:data-cy="sponsorGroupDataCy(sponsorGroupIndex)"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
v-for="sponsor in sponsors"
|
v-for="sponsor in sponsorGroup"
|
||||||
:key="sponsor.name"
|
:key="`${sponsorGroupIndex}-${sponsor.name}`"
|
||||||
:src="sponsor.src"
|
:src="sponsor.src"
|
||||||
:alt="sponsor.name"
|
:alt="sponsorLogoAlt(sponsor, sponsorGroupIndex)"
|
||||||
class="sponsors__logo"
|
class="sponsors__logo"
|
||||||
data-cy="sponsor-logo"
|
:data-cy="sponsorLogoDataCy(sponsorGroupIndex)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="projects" data-cy="projects">
|
<section class="projects" data-cy="projects">
|
||||||
|
|
@ -883,21 +919,62 @@ const projects: Project[] = [
|
||||||
margin: 0 0 3rem 0;
|
margin: 0 0 3rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sponsors__row {
|
.sponsors__carousel {
|
||||||
|
--sponsors-edge-fade: 50px;
|
||||||
|
--sponsors-logo-gap: clamp(2.75rem, 4vw, 4.25rem);
|
||||||
|
|
||||||
|
width: 85%;
|
||||||
|
margin: 0 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
mask-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent,
|
||||||
|
black var(--sponsors-edge-fade),
|
||||||
|
black calc(100% - var(--sponsors-edge-fade)),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
-webkit-mask-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent,
|
||||||
|
black var(--sponsors-edge-fade),
|
||||||
|
black calc(100% - var(--sponsors-edge-fade)),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsors__track {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
width: max-content;
|
||||||
|
animation: sponsors-scroll 20s linear infinite;
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsors__group {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
gap: var(--sponsors-logo-gap);
|
||||||
gap: 2.5rem 3rem;
|
padding-right: var(--sponsors-logo-gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sponsors__logo {
|
.sponsors__logo {
|
||||||
height: 60px;
|
height: clamp(78px, 7vw, 96px);
|
||||||
width: auto;
|
width: auto;
|
||||||
max-width: 160px;
|
max-width: 220px;
|
||||||
|
flex: 0 0 auto;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes sponsors-scroll {
|
||||||
|
from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.projects {
|
.projects {
|
||||||
background: var(--color-cream);
|
background: var(--color-cream);
|
||||||
padding: 5rem 2rem;
|
padding: 5rem 2rem;
|
||||||
|
|
@ -1228,6 +1305,15 @@ const projects: Project[] = [
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sponsors__carousel {
|
||||||
|
width: min(100%, 680px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsors__logo {
|
||||||
|
height: clamp(68px, 18vw, 86px);
|
||||||
|
max-width: 190px;
|
||||||
|
}
|
||||||
|
|
||||||
.journey__cards {
|
.journey__cards {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue