Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions packages/app/cypress/e2e/landing-performance.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('Landing page performance', () => {
cy.viewport(412, 823);
cy.request('/')
.its('body')
.should('contain', 'See more supporters')
.should('contain', 'See full quotes')
.and('contain', 'data-testid="launch-banner"');

cy.intercept('GET', '**/_next/static/**/*.js', (request) => {
Expand All @@ -65,11 +65,14 @@ describe('Landing page performance', () => {
});

cy.get('[data-testid="launch-banner"]').should('be.visible');
cy.get('[data-testid="intro-section"]').should('contain.text', 'See more supporters');
cy.get('[data-testid="quote-carousel-more-row"]')
cy.get('[data-testid="intro-section"]').should(
'contain.text',
'See full quotes & more supporters',
);
cy.get('[data-testid="supporters-more-row"]')
.should('have.class', 'justify-end')
.find('a')
.should('have.text', 'See more supporters →');
.should('have.text', 'See full quotes & more supporters →');
expectLowCls();
});

Expand All @@ -84,7 +87,10 @@ describe('Landing page performance', () => {

cy.get('html').should('have.attr', 'data-landing-banner-dismissed');
cy.get('[data-testid="launch-banner"]').should('not.exist');
cy.get('[data-testid="intro-section"]').should('contain.text', 'See more supporters');
cy.get('[data-testid="intro-section"]').should(
'contain.text',
'See full quotes & more supporters',
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale supporter logo preload test

Medium Severity

This spec still expects / to preload exactly one supporter logo (/logos/minimax.svg) from the old carousel’s first quote. SupportersStrip only renders org names, so that image is no longer on the landing HTML and the preload assertion fails.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cb1ee28. Configure here.

expectLowCls();
});

Expand Down
34 changes: 12 additions & 22 deletions packages/app/src/components/intro-section.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { QuoteCarousel } from '@/components/quote-carousel';
import { SupportersStrip } from '@/components/supporters-strip';
import { QUOTES, CAROUSEL_ORGS, CAROUSEL_LABELS } from '@/components/quotes/quotes-data';
import type { Locale } from '@/lib/i18n';

// Carousel order follows QUOTES order — carousel orgs are listed first there.
const carouselQuotes = QUOTES.filter((q) => (CAROUSEL_ORGS as readonly string[]).includes(q.org));

const CAROUSEL_OVERRIDES = {
labels: CAROUSEL_LABELS,
};
// Strip order follows QUOTES order — supporter orgs are listed first there.
const supporterOrgs = [
...new Set(
QUOTES.filter((q) => (CAROUSEL_ORGS as readonly string[]).includes(q.org)).map((q) => q.org),
),
].map((org) => CAROUSEL_LABELS[org] ?? org);

const STRINGS = {
en: {
Expand All @@ -23,19 +23,10 @@ const STRINGS = {
export function IntroSection({ locale = 'en' }: { locale?: Locale } = {}) {
const isZh = locale === 'zh';
const t = STRINGS[locale];
// Quotes fall back to the English original until a translation lands.
const quotes = isZh
? carouselQuotes.map((q) => ({
...q,
text: q.textZh ?? q.text,
title: q.titleZh ?? q.title,
}))
: carouselQuotes;
return (
<section className="py-8 md:py-12">
{/* Mint-tinted supporters band: the quote carousel already carries the
org strip, so the section frames it with an editorial heading
instead of card chrome. */}
{/* Mint-tinted supporters band: quote text lives on /quotes now — the
band keeps just the org strip and a link out, saving vertical space. */}
<div
data-testid="intro-section"
className="rounded-2xl bg-accent px-5 py-8 md:px-10 md:py-10 dark:bg-card dark:border dark:border-border"
Expand All @@ -45,11 +36,10 @@ export function IntroSection({ locale = 'en' }: { locale?: Locale } = {}) {
{t.heading}
</h2>
<div className="mt-8">
<QuoteCarousel
quotes={quotes}
overrides={CAROUSEL_OVERRIDES}
<SupportersStrip
orgs={supporterOrgs}
moreHref={isZh ? '/zh/quotes' : '/quotes'}
moreLabel={isZh ? '查看业界评价 →' : undefined}
moreLabel={isZh ? '查看完整评价与更多支持者 →' : undefined}
/>
</div>
</div>
Expand Down
214 changes: 0 additions & 214 deletions packages/app/src/components/quote-carousel.tsx

This file was deleted.

45 changes: 45 additions & 0 deletions packages/app/src/components/supporters-strip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use client';

import Link from 'next/link';

import { track } from '@/lib/analytics';

export interface SupportersStripProps {
/** Display names shown in the org strip, in display order */
orgs: string[];
/** Link to the page with all quotes and supporters */
moreHref: string;
/** Label for the moreHref link (default "See full quotes & more supporters →") */
moreLabel?: string;
}

/**
* Compact replacement for the landing quote carousel: renders the supporter
* org strip plus a single link out to the full quotes page instead of a
* rotating quote block, saving vertical space above the fold.
*/
export function SupportersStrip({ orgs, moreHref, moreLabel }: SupportersStripProps) {
return (
<div className="flex flex-col gap-4">
{/* Org name strip */}
<div className="flex flex-wrap justify-center gap-x-6 md:gap-x-8 gap-y-2 mx-4">
{orgs.map((org) => (
<span key={org} className="text-xs font-semibold tracking-wide uppercase text-[#808488]">
{org}
</span>
))}
</div>

<div className="flex justify-end" data-testid="supporters-more-row">
<Link
href={moreHref}
prefetch={false}
className="text-xs font-bold text-brand hover:underline"
onClick={() => track('quote_carousel_see_more_clicked')}
>
{moreLabel ?? 'See full quotes & more supporters →'}
</Link>
</div>
</div>
);
}